package com.sdleyou.treepro.common.service.impl;

import com.sdleyou.treepro.common.model.dao.AchievementDO;
import com.sdleyou.treepro.common.model.dao.UserDO;
import com.sdleyou.treepro.common.model.enums.RedisLockEnum;
import com.sdleyou.treepro.common.model.vo.AchievementVO;
import com.sdleyou.treepro.common.model.vo.CertificateVO;
import com.sdleyou.treepro.common.model.vo.UserAchievementVO;
import com.sdleyou.treepro.common.service.AchievementManager;
import com.sdleyou.treepro.common.service.CertificateManager;
import com.sdleyou.treepro.common.service.MongoPageManager;
import com.sdleyou.treepro.common.service.UserAchievementManager;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class UserAchievementManagerImpl implements UserAchievementManager {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private MongoPageManager mongoPageManager;
    @Autowired
    private AchievementManager achievementManager;
    @Autowired
    private CertificateManager certificateManager;
    @Autowired
    private RedissonClient redissonClient;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 获取成就详情
     */
    @Override
    public UserAchievementVO achievementInfo(String userId) {
        AchievementVO achievement = achievementManager.getAchievement();
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);

        //1500步=270g碳排放
        //一棵树绿化面积大概3平米
        UserAchievementVO userAchievementVO = new UserAchievementVO();
        BeanUtils.copyProperties(achievement, userAchievementVO);
        userAchievementVO.setTotalGreenSpace(achievement.getCurrentTarget() * 3);//全网绿化面积
        userAchievementVO.setSubCarbon(achievement.getTotalStep() / 1500 * 270 / 1000.0);//减少碳排放
        userAchievementVO.setUserTotalTree(userDO.getTotalTree().longValue());
        userAchievementVO.setUserGreenSpace((long) (userDO.getTotalTree() * 3));//用户绿化面积
        userAchievementVO.setVolunteerCert(userDO.getVolunteerCert());
        if (userDO.getHasQMYW()) {
            CertificateVO certificate = certificateManager.getCertificateInfo(userDO.getUserId(), "QMYW");
            userAchievementVO.setDutyCert(certificate.getCImg());
        }
        if (userDO.getHasGTLH()) {
            CertificateVO certificate = certificateManager.getCertificateInfo(userDO.getUserId(), "GTLH");
            userAchievementVO.setHonourCert(certificate.getCImg());
        }

        return userAchievementVO;
    }

    /**
     * 更新全网总种树量
     */
    @Override
    public void updateTotalTree(Long num) {
        //获取内存锁
        RLock fairLock = redissonClient.getFairLock(RedisLockEnum.ACHIEVEMENT.name());
        try {
            boolean res = fairLock.tryLock(2, 10, TimeUnit.SECONDS);
            if (res) {
                Query query = new Query();
                AchievementDO achievementDO = mongoTemplate.findOne(query, AchievementDO.class);
                if (achievementDO != null) {
                    Update update = new Update();
                    update.set("current_target", achievementDO.getCurrentTarget() + num);
                    mongoTemplate.updateFirst(query, update, AchievementDO.class);
                }
            }
        } catch (InterruptedException e) {
            logger.info("updateTotalTree 公平锁操作异常{}、{}", e.getStackTrace(), e.getMessage());
        } finally {
            //解锁
            fairLock.unlock();
        }
    }

    /**
     * 更新总步数
     */
    @Override
    public void updateTotalStep(Long num) {
        //获取内存锁
        RLock fairLock = redissonClient.getFairLock(RedisLockEnum.ACHIEVEMENT.name());
        try {
            boolean res = fairLock.tryLock(2, 10, TimeUnit.SECONDS);
            if (res) {
                Query query = new Query();
                AchievementDO achievementDO = mongoTemplate.findOne(query, AchievementDO.class);
                if (achievementDO != null) {
                    Update update = new Update();
                    update.set("total_step", achievementDO.getTotalStep() + num);
                    mongoTemplate.updateFirst(query, update, AchievementDO.class);
                }
            }
        } catch (InterruptedException e) {
            logger.info("updateTotalStep 公平锁操作异常{}、{}", e.getStackTrace(), e.getMessage());
        } finally {
            //解锁
            fairLock.unlock();
        }
    }
}
